from django.db.models import Q, Count

from auto_dj_test.conf.MyLogger import MyLogger
from aweirunner import models
from aweirunner.utils.day import get_day, get_week, get_month


def get_project_apis(project_id) -> dict:
    """
    统计项目中所有的api
    """
    # 查询除了tag为4以外的api, Q 是复杂运算的标记，
    query = models.API.objects.filter(delete=0).filter(~Q(tag=4))
    if project_id:
        query = query.filter(project_id=project_id)
    print(query.count())
    return {"用户创建": query.count()}


def aggregate_case_by_tag(project_id):
    """
    按照分类统计项目中的用例
    """
    query = models.Case.objects
    if project_id:
        query = query.filter(project_id=project_id)
    case_count: dict = query.aggregate(
        冒烟用例=Count("pk", filter=Q(tag=1)),
        集成用例=Count("pk", filter=Q(tag=2)),
        监控脚本=Count("pk", filter=Q(tag=3)),
        核心用例=Count("pk", filter=Q(tag=4)),
    )
    return list(case_count.keys()), list(case_count.values())


def aggregate_reports_by_type(project_id):
    """
    按照类型统计项目中的报告
    """
    query = models.Report.objects
    if project_id:
        query = query.filter(project_id=project_id)
    report_count: dict = query.aggregate(
        调试=Count("pk", filter=Q(type=1)),
        异步=Count("pk", filter=Q(type=2)),
        定时=Count("pk", filter=Q(type=3)),
        部署=Count("pk", filter=Q(type=4)),
    )
    return list(report_count.keys()), list(report_count.values())


def get_daily_count(project_id, model_name, start, end):
    # 生成日期list, ['08-12', '08-13', ...]
    recent_days = [get_day(n)[5:] for n in range(start, end)]
    models_mapping = {"api": models.API, "case": models.Case, "report": models.Report}
    model = models_mapping[model_name]
    query = model.objects
    if model_name == "api":
        query = query.filter(~Q(tag=4))

    # 统计给定日期范围内，每天创建的条数
    count_data: list = (
        query.filter(
            project_id=project_id, create_time__range=[get_day(start), get_day(end)]
        )
        .extra(select={"create_time": "DATE_FORMAT(create_time,'%%m-%%d')"})
        .values("create_time")
        .annotate(counts=Count("id"))
        .values("create_time", "counts")
    )
    # list转dict, key是日期, value是统计数
    create_time_count_mapping = {
        data["create_time"]: data["counts"] for data in count_data
    }

    # 日期为空的key，补0
    count = [create_time_count_mapping.get(d, 0) for d in recent_days]
    return {"days": recent_days, "count": count}


def get_project_daily_create(project_id):
    """
    项目 从今天算起这周创建的api, case, report
    """
    start = -6
    end = 1
    count_mapping = {}
    for model in ("api", "case", "report"):
        count_mapping[model] = get_daily_count(project_id, model, start, end)
    return count_mapping


def get_project_detail_v2(pk):
    """统计项目api，case，report总数和每日创建"""
    logger = MyLogger(get_project_detail_v2.__name__).logger
    # 统计api类型以及数目
    logger.debug("统计api类型以及数目")
    api_dict = get_project_apis(pk)
    # 统计用例case各个类型以及数目
    logger.debug("统计用例case各个类型以及数目")
    case_tag, case_tag_count = aggregate_case_by_tag(pk)
    # 统计各个类型产生的报告数量
    logger.debug("统计各个类型产生的报告数量")
    report_type, report_type_count = aggregate_reports_by_type(pk)
    # 统计每天创建的api，case，report
    logger.debug("统计每天创建的api，case，report")
    daily_create_count = get_project_daily_create(pk)
    res = {
        "api_count_by_create_type": {
            "type": api_dict.keys(),
            "count": api_dict.values(),
        },
        "case_count_by_tag": {"tag": case_tag, "count": case_tag_count},
        "report_count_by_type": {"type": report_type, "count": report_type_count},
        "daily_create_count": daily_create_count,
    }
    return res


def aggregate_reports_by_status(project_id):
    """按照状态统计项目中的报告"""
    query = models.Report.objects
    if project_id:
        query = query.filter(project_id=project_id)
    report_count: dict = query.aggregate(
        失败=Count("pk", filter=Q(status=0)),
        成功=Count("pk", filter=Q(status=1)),
    )
    return list(report_count.keys()), list(report_count.values())


def get_sql_dateformat(date_type):
    # 按对应周期返回对应格式化时间
    if date_type == "week":
        create_time = "YEARWEEK(create_time,'%%Y-%%m-%%d')"
    elif date_type == "month":
        create_time = "DATE_FORMAT(create_time,'%%Y%%m')"
    elif date_type == "day":
        create_time = "DATE_FORMAT(create_time,'%%Y-%%m-%%d')"
    return create_time


def get_recent_date(date_type):
    if date_type == "day":
        return [get_day(n) for n in range(-5, 1)]
    elif date_type == "week":
        return [get_week(n) for n in range(-5, 1)]
    elif date_type == "month":
        return [get_month(n) for n in range(-5, 1)]


def list2dict(arr):
    keys = []
    values = []
    for d in arr:
        keys.append(str(d.get("create_time")))
        values.append(d.get("counts"))
    return dict(zip(keys, values))


def complete_list(arr, date_type):
    # {日期: 数量}
    mapping = list2dict(arr)
    date_list = get_recent_date(date_type)
    count = [mapping.get(d, 0) for d in date_list]
    return count


def aggregate_reports_or_case_bydate(date_type, model):
    """按月和周统计报告创建数量"""
    create_time = get_sql_dateformat(date_type)
    qs = (
        # 为查询结果添加一个名为 "create_time" 的附加字段。
        model.objects.extra(select={"create_time": create_time})
        .values(
            "create_time",
        )
        .annotate(counts=Count("id"))
        .values("create_time", "counts")
    )

    qs = list(qs)
    complete_list(qs, date_type)

    # 查询结果是按照时间升序，取最后6条
    # 没有的补0
    values = complete_list(qs, date_type)

    return values


def aggregate_apis_bydate(date_type, is_yapi=False) -> dict:
    """按照日，周，月统计项目中手动创建和从yapi导入的接口数量"""
    create_time = get_sql_dateformat(date_type)

    query = models.API.objects.filter(~Q(tag=4))
    if is_yapi:
        query = query.filter(creator="yapi")
    else:
        query = query.filter(~Q(creator="yapi"))

    count_data: dict = (
        query.extra(select={"create_time": create_time})
        .values(
            "create_time",
        )
        .annotate(counts=Count("id"))
        .values("create_time", "counts")
    )

    # 查询结果是按照时间升序，取最后6条
    # 没有的补0
    count = complete_list(count_data, date_type)

    return count
